package cn.coldleaf.wiki.services.impl;

import cn.coldleaf.wiki.configure.AppConfig;
import cn.coldleaf.wiki.errors.UserCreateException;
import cn.coldleaf.wiki.errors.UserExistsException;
import cn.coldleaf.wiki.errors.UserNotExistsException;
import cn.coldleaf.wiki.errors.UserUpdateException;
import cn.coldleaf.wiki.mappers.UserMapper;
import cn.coldleaf.wiki.pojo.dto.UserLoginDto;
import cn.coldleaf.wiki.pojo.dto.UserModifyPwdDto;
import cn.coldleaf.wiki.pojo.dto.UserQueryDto;
import cn.coldleaf.wiki.pojo.dto.UserSaveDto;
import cn.coldleaf.wiki.pojo.entity.BaseEntity;
import cn.coldleaf.wiki.pojo.entity.UserEntity;
import cn.coldleaf.wiki.pojo.vo.UserInfoVo;
import cn.coldleaf.wiki.pojo.vo.UserLoginVo;
import cn.coldleaf.wiki.services.UserService;
import cn.coldleaf.wiki.utils.SHAUtil;
import cn.coldleaf.wiki.utils.StringUtil;
import cn.coldleaf.wiki.utils.TokenUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * @datetime 2023/10/17 下午8:41
 * @user cold
 **/
@Service
@AllArgsConstructor
public class UserServiceImpl implements UserService, InitializingBean {
    private final UserMapper userMapper;
    private final AppConfig appConfig;

    private String pwdEncrypt(String pwd, String salt){
        StringBuilder builder = new StringBuilder(pwd)
                .append(salt)
                .append(salt)
                .append(pwd)
                .append(salt);
        return SHAUtil.encrypt(builder.toString());
    }
    /**
     * 用户登录
     *
     * @param dto
     * @datetime 2023-10-17 18:51:37
     * @user cold
     */
    @Override
    public UserLoginVo login(UserLoginDto dto) {
        UserEntity user = userMapper.selectOne(new QueryWrapper<UserEntity>()
                .lambda()
                .eq(UserEntity::getUsername, dto.getUsername())
                .eq(UserEntity::getEnabled, 1)
                .orderByDesc(BaseEntity::getAddTime)
                .last(" limit 1"));
        if (user != null){
            if (pwdEncrypt(dto.getPassword(),user.getSalt()).equals(user.getPassword())){
                String token = TokenUtil.genToken(user.getId(),appConfig.getTokenKey());
                UserLoginVo loginVo = new UserLoginVo();
                loginVo.setToken(token);
                return loginVo;
            }
        }
        return null;
    }

    /**
     * 获取用户信息
     *
     * @param dto
     * @datetime 2023-10-17 20:28:07
     * @user cold
     */
    @Override
    public UserInfoVo getInfo(UserQueryDto dto) {
        if (dto.getUserId() == null){
            dto.setUserId(dto.getOperator());
        }
        UserEntity user = userMapper.selectById(dto.getUserId());
        if (user != null){
            UserInfoVo vo = new UserInfoVo();
            BeanUtils.copyProperties(user,vo );
            return vo;
        }
        return null;
    }

    /**
     * 保存用户
     *
     * @param dto
     * @datetime 2023-10-17 20:35:37
     * @user cold
     */
    @Override
    @Transactional
    public UserInfoVo saveUser(UserSaveDto dto) {
        long count = userMapper.selectCount(new QueryWrapper<UserEntity>()
                .lambda()
                .eq(UserEntity::getUsername,dto.getUsername())
                .last(" limit 1")
        );
        if (count > 0){
            throw new UserExistsException();
        }
        UserEntity entity = new UserEntity();
        entity.setUsername(dto.getUsername());
        entity.setNickname(dto.getNickname());
        entity.setAvatar(dto.getAvatar());
        entity.setBirthday(dto.getBirthday());
        entity.setGender(dto.getGender());
        entity.setEmail(dto.getEmail());
        entity.setMobile(dto.getMobile());
        entity.setAddUser(dto.getOperator());
        entity.setUpdateUser(dto.getOperator());
        // 设置密码
        String salt = StringUtil.randomStr(8);
        entity.setSalt(salt);
        entity.setPassword(pwdEncrypt(dto.getPassword(),salt));
        // 创建用户文件夹
        StringBuilder builder = new StringBuilder(appConfig.getHomeDir());
        if (builder.lastIndexOf("/") == builder.length() - 1){
            builder.append(entity.getUsername())
                    .append("/");
        }else {
            builder.append("/")
                    .append(entity.getUsername())
                    .append("/");
        }
        entity.setHome(builder.toString());
        int ret =userMapper.insert(entity);
        if (ret > 0) {
            String [] fileTypes = new String[]{
                    builder.toString() + "image",
                    builder.toString() + "video",
                    builder.toString() + "music",
                    builder.toString() + "other"};
            for (String fileType : fileTypes) {
                new File(fileType).mkdirs();
            }
            UserInfoVo vo = new UserInfoVo();
            BeanUtils.copyProperties(entity, vo);
            return vo;
        }
        throw new UserCreateException();
    }

    /**
     * 修改用户
     *
     * @param dto
     * @datetime 2023-10-17 20:35:37
     * @user cold
     */
    @Override
    @Transactional
    public UserInfoVo modifyUser(UserSaveDto dto) {
        UserEntity user = userMapper.selectById(dto.getId());
        if (user == null){
            throw new UserNotExistsException();
        }
        boolean isUpdate = false;
        UserEntity update = new UserEntity();
        if (dto.getNickname() != null && !StringUtil.equals(user.getNickname(),dto.getNickname())){
            update.setNickname(dto.getNickname());
            isUpdate = true;
        }
        if (dto.getAvatar() != null && !StringUtil.equals(user.getAvatar(),dto.getAvatar())){
            update.setAvatar(dto.getAvatar());
            isUpdate = true;
        }
        if (dto.getBirthday() != null && !StringUtil.equals(user.getBirthday(),dto.getBirthday())){
            update.setBirthday(dto.getBirthday());
            isUpdate = true;
        }
        if (dto.getGender() != null && !dto.getGender().equals(user.getGender())){
            update.setGender(dto.getGender());
            isUpdate = true;
        }
        if (dto.getEmail() != null && !StringUtil.equals(user.getEmail(),dto.getEmail())){
            update.setEmail(dto.getEmail());
            isUpdate = true;
        }
        if (dto.getMobile() != null && !StringUtil.equals(user.getMobile(),dto.getMobile())){
            update.setMobile(dto.getMobile());
            isUpdate = true;
        }
        if (dto.getEnabled() != null && !dto.getEnabled().equals(user.getEnabled())){
            update.setEnabled(dto.getEnabled());
            isUpdate = true;
        }
        if (isUpdate){
            update.setId(dto.getId());
            update.setUpdateUser(dto.getOperator());
            int ret = userMapper.updateById(update);
            if (ret > 0){
                user = userMapper.selectById(dto.getId());
                UserInfoVo vo = new UserInfoVo();
                BeanUtils.copyProperties(user,vo);
                return vo;
            }
        }
        throw new UserUpdateException();
    }

    /**
     * 修改密码
     *
     * @param dto
     * @datetime 2023-10-19 09:58:29
     * @user cold
     */
    @Override
    public int resetPwd(UserModifyPwdDto dto) {
        UserEntity user = userMapper.selectById(dto.getUserId());
        if (user == null){
            return 0;
        }
        return changePwd(dto);
    }

    /**
     * 修改密码
     *
     * @param dto
     * @datetime 2023-10-19 10:04:20
     * @user cold
     */
    @Override
    public int modifyPwd(UserModifyPwdDto dto) {
        if (dto.getUserId() == null){
            dto.setUserId(dto.getOperator());
        }
        UserEntity user = userMapper.selectById(dto.getUserId());
        if (user == null){
            return 0;
        }
        String encryptPwd = pwdEncrypt(dto.getOriginalPassword(),user.getSalt());
        if (!encryptPwd.equals(user.getPassword())){
            return 0;
        }
        return changePwd(dto);
    }

    /**
     * 查询用户列表
     *
     * @param dto
     * @datetime 2023-10-28 11:52:58
     * @user cold
     */
    @Override
    public IPage<UserInfoVo> searchList(UserQueryDto dto) {
        Page<UserEntity> page = new Page<>();
        page.setCurrent(dto.getCurrent());
        page.setSize(dto.getPageSize());
        LambdaQueryWrapper<UserEntity> query = new QueryWrapper<UserEntity>().lambda();
        if (StringUtil.isNotBlank(dto.getKeyWord())){
            query.likeRight(UserEntity::getUsername,dto.getKeyWord())
                    .or()
                    .likeRight(UserEntity::getNickname,dto.getKeyWord())
                    .or()
                    .likeRight(UserEntity::getMobile,dto.getKeyWord())
                    .or()
                    .likeRight(UserEntity::getEmail,dto.getKeyWord());
        }
        page = userMapper.selectPage(page,query);
        List<UserInfoVo> records = new ArrayList<>();
        if (page.getRecords() != null){
            for (UserEntity record : page.getRecords()) {
                UserInfoVo vo = new UserInfoVo();
                BeanUtils.copyProperties(record,vo);
                records.add(vo);
            }
        }
        Page<UserInfoVo> voPage = new Page<>();
        voPage.setTotal(page.getTotal());
        voPage.setCurrent(page.getCurrent());
        voPage.setSize(page.getSize());
        voPage.setRecords(records);
        return voPage;
    }

    /**
     * 修改密码
     * @datetime 2023-10-19 10:08:30
     * @user cold
     **/
    private int changePwd(UserModifyPwdDto dto){
        String salt = StringUtil.randomStr(8);
        String pwd = pwdEncrypt(dto.getNewPassword(),salt);
        UserEntity update = new UserEntity();
        update.setId(dto.getUserId());
        update.setPassword(pwd);
        update.setSalt(salt);
        update.setUpdateUser(dto.getOperator());
        int ret = userMapper.updateById(update);
        if (ret > 0){
            return  1;
        }
        return 0;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // 创建初始管理员用户
        long count = userMapper.selectCount(new QueryWrapper<>());
        if (count  == 0){
            UserSaveDto admin = new UserSaveDto();
            admin.setUsername("admin");
            admin.setNickname("管理员");
            admin.setAvatar("");
            admin.setBirthday("1970-01-01");
            admin.setEmail("");
            admin.setMobile("");
            admin.setPassword("admin");
            this.saveUser(admin);
        }
    }
}
